<?php
declare(strict_types=1);

use App\Common\Extend\Guard\Guard;
use App\Common\Extend\Guard\UserAuth;
use App\Common\Modular\System\Serve\CachingServe;
use App\Common\Modular\System\Serve\ConfigureServe;
use Core\Exception\PrintException;
use Hyperf\Context\ApplicationContext;
use Hyperf\Logger\LoggerFactory;
use JetBrains\PhpStorm\ArrayShape;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Log\LoggerInterface;
use Psr\SimpleCache\CacheInterface;
use Zms\Exception\AppException;
use Zms\Exception\DataException;
use Zms\Validate\Validate;
use Zms\Unit\Is;
use function Hyperf\Support\env;


if (function_exists('container') === false) {
    /**
     * 获取容器单例
     * @template T
     * @param string<T> $className
     * @return T
     */
    function container(string $className): mixed
    {
        try {
            return ApplicationContext::getContainer()->get($className);
        } catch (NotFoundExceptionInterface|ContainerExceptionInterface) {
            return null;
        }
    }
}

if (function_exists('caching') === false) {

    /**
     * 数据库缓存工具,防止重要数据和缓存被清空
     */
    function caching(): CachingServe
    {
        return container(CachingServe::class);
    }
}


if (function_exists('IsDebug') === false) {
    /**
     * 当前是否是调试模式
     */
    function IsDebug(): bool
    {
        return env('APP_ENV', '') === 'dev';
    }
}


if (function_exists('configure') === false) {
    /**
     * 系统配置读取
     */
    function configure(string $key, mixed $default = null): mixed
    {
        return container(ConfigureServe::class)->get($key, $default);
    }
}


if (function_exists('logger') === false) {
    /**
     * 日志记录组件
     */
    function logger($group = 'default', $name = 'app'): LoggerInterface
    {
        return container(LoggerFactory::class)->get($name, $group);
    }
}


if (function_exists('ServerOs') === false) {

    #[ArrayShape(['type' => 'string', 'name' => 'string', 'os' => 'string'])]
    function ServerOs(): array
    {
        $os = strtolower(PHP_OS);
        if ($os === 'linux') {
            //wsl下的linux环境
            if (isset($_SERVER['WSL_DISTRO_NAME'])) {
                return ['type' => 'wsl', 'name' => "[WSL]{$_SERVER['WSL_DISTRO_NAME']}", 'os' => 'linux'];
            }
            //docker中的Linux环境
            $scanned = strtolower(php_ini_scanned_files() ?: '');
            if ($scanned && preg_match('/(docker)/', $scanned)) {
                return ['type' => 'docker', 'name' => php_uname('r'), 'os' => 'linux'];
            }
            $bin = $_SERVER['_'] ?? '';
            if ($bin && preg_match('/(php)/', $bin)) {
                return ['type' => 'linux', 'name' => php_uname('r'), 'os' => 'linux php'];
            }
            //原生linux环境
            return ['type' => 'linux', 'name' => php_uname('r'), 'os' => 'linux swoole-cli'];
        }
        //windows+swoole-cli下的环境
        if (preg_match('/(cygwin)/', $os)) {
            return ['type' => 'cygwin', 'name' => "windows", 'os' => 'windows'];
        }
        //未知环境
        return ['type' => 'unknown', 'name' => "unknown", 'os' => $os];
    }
}

if (function_exists('event') === false) {
    /**
     * 事件触发器
     * @param object $event
     * @return object|null
     */
    function event(object $event): ?object
    {
        try {
            return ApplicationContext::getContainer()->get(EventDispatcherInterface::class)->dispatch($event);
        } catch (NotFoundExceptionInterface|ContainerExceptionInterface) {
            return null;
        }
    }
}


if (function_exists('validate') === false) {
    /**
     * 加载验证器
     * @param array $rules
     * @param array $value
     * @param array $lable
     * @return Validate
     */
    function validate(array $rules = [], array $value = [], array $lable = []): Validate
    {
        $validate = new Validate();
        if (Is::notEmpty($rules)) $validate->setRules($rules);
        if (Is::notEmpty($value)) $validate->setData($value);
        if (Is::notEmpty($lable)) $validate->setLabels($lable);
        return $validate;
    }
}


if (function_exists('cache') === false) {
    /**
     * 缓存工具
     * @return CacheInterface
     */
    function cache(): CacheInterface
    {
        return container(CacheInterface::class);
    }
}

if (function_exists('show') === false) {
    /**
     * 打印数据
     * @param mixed $data
     * @throws PrintException
     */
    function show(mixed $data)
    {
        throw new PrintException($data);
    }
}


if (function_exists('guard') === false) {
    /**
     * 获取授权组件实例
     * @param string $guard
     * @return Guard
     * @throws AppException
     * @throws DataException
     */
    function guard(string $guard): Guard
    {
        return UserAuth::guard($guard);
    }
}


if (function_exists('ServiceReturn') === false) {
    /**
     * 服务响应
     * @param bool $state 状态
     * @param string $message 消息
     * @param mixed|null $data 数据
     * @return array
     */
    function ServiceReturn(bool $state, string $message = '', mixed $data = null): array
    {
        $result = [
            'state' => $state,
            'message' => $message ?: ($state ? 'success' : 'error')
        ];
        if (is_null($data)) return $result;
        $result['data'] = $data;
        return $result;
    }
}
